import { Color, Mesh, Shader, Vector2 } from 'three'
import { gsap } from 'gsap'

const modifyCityMaterial = (mesh: Mesh) => {
  if (Array.isArray(mesh.material)) return
  mesh.material.onBeforeCompile = (shader) => {
    console.log(shader.vertexShader)
    console.log(shader.fragmentShader)

    addGradColor(mesh, shader)
    addSpread(shader)
  }
}
export default modifyCityMaterial

/** 添加渐变色 */
function addGradColor(mesh: Mesh, shader: Shader) {
  mesh.geometry.computeBoundingBox()
  const { min, max } = mesh.geometry.boundingBox!
  // 获取物体的高度差
  const uHeight = max.y - min.y
  shader.uniforms.uTopColor = {
    value: new Color('#7897d7'),
  }
  shader.uniforms.uHeight = {
    value: uHeight,
  }

  shader.vertexShader = shader.vertexShader.replace(
    '#include <common>',
    `
      #include <common>
      varying vec3 vPosition;
      `
  )
  shader.vertexShader = shader.vertexShader.replace(
    '#include <begin_vertex>',
    `
      #include <begin_vertex>
      vPosition = position;
      `
  )
  shader.fragmentShader = shader.fragmentShader.replace(
    '#include <common>',
    `
      #include <common>
      
      uniform vec3 uTopColor;
      uniform float uHeight;

      varying vec3 vPosition;
      `
  )
  shader.fragmentShader = shader.fragmentShader.replace(
    '#include <dithering_fragment>',
    `
      #include <dithering_fragment>
      vec4 distGradColor = gl_FragColor;

      // 设置混合的百分比
      float gradMix = (vPosition.y + uHeight * 0.2) / uHeight;
      // 计算出混合颜色
      vec3 gradMixColor = mix(distGradColor.xyz, uTopColor, gradMix);
      gl_FragColor = vec4(gradMixColor, 1);
      //#end#
      `
  )
}

function addSpread(shader: Shader) {
  shader.uniforms.uSpreadCenter = { value: new Vector2(0, 0) }
  shader.uniforms.uTime = { value: 0 }
  shader.uniforms.uSpreadWidth = { value: 300 }

  shader.fragmentShader = shader.fragmentShader.replace(
    '#include <common>',
    `
    #include <common>

    uniform vec2 uSpreadCenter;
    uniform float uTime;
    uniform float uSpreadWidth;
    `
  )

  shader.fragmentShader = shader.fragmentShader.replace(
    '//#end#',
    `
    float dis = distance(vPosition.xz, uSpreadCenter);
    float spreadIndex = (dis - uTime) * (dis - uTime) - uSpreadWidth;

    if(spreadIndex < 0.0){
      gl_FragColor = mix(gl_FragColor, vec4(.8, .8, 1, 1), -spreadIndex / uSpreadWidth);
    }

    //#end#
    `
  )

  gsap.to(shader.uniforms.uTime, { value: 800, duration: 4, repeat: -1 })
}
